
//---------------------------------------------------------------------------
// Copyright (c) 2011 Texas Instruments, Inc.
// This is an unpublished work created in the year stated above.
// Texas Instruments owns all rights in and to this work and
// intends to maintain and protect it as an unpublished copyright.
// In the event of either inadvertent or deliberate publication,
// the above stated date shall be treated as the year of first
// publication. In the event of such publication, Texas Instruments
// intends to enforce its rights in the work under the copyright
// laws as a published work.
//----------------------------------------------------------------------------
// Filename                : monterey_uart.c
//
// Functional Description  : UART state machine
//----------------------------------------------------------------------------

#include "DRV922XX.h"//#include "MSP430DRC4300.h"
#include "monterey_uart.h"
#include "message_protocol_application.h"//#include "message_protocol.h"

unsigned char rx_byte_count = 0;					/*!< Number of received bytes of the current UART message */
unsigned char *rx_data_ptr = &uart_rx_buffer[0];	/*!< Pointer to memory to store received UART messages */
unsigned char *curr_data_ptr = &uart_rx_buffer[0];	/*!< Pointer for tracking received bytes */

unsigned char tx_byte_count = 0;					/*!< Number of transmitted bytes of the current UART message */
unsigned char tx_bytes_to_send = 0;					/*!< Number of total bytes to send for the current UART message */
unsigned char *tx_data_ptr = 0;						/*!< Pointer to memory to send transmitted UART messages from */

unsigned char uart_rx_buffer[UART_MESSAGE_SIZE];	/*!< Receive buffer for incoming UART messages */
unsigned char response_buffer_ACK[16];

unsigned char uart_receiving_message = 0;			/*!< Non-zero if receiving message, but incomplete */
unsigned char uart_transmitting_message = 0;		/*!< Non-zero if transmitting message, but incomplete */

unsigned int uart_byte_timer = 0;					/*!< UART timeout timer */

typedef enum 
{
	tx_state_idle,
	tx_state_delay,
	tx_state_send_byte
} Uart_Transmit_States;

Uart_Transmit_States uart_tx_state = tx_state_idle;

void uart_tx_state_machine();


/*
 *  \fn uart_init()
 *  \brief Initializes the UART in the microcontroller.
 */
void uart_init()
{
	P3SEL |= (BIT5 | BIT6);				 		// P3.5 - P3.6 for UART - NOTE: DO NOT SET P3DIR bits for UART to work
	
	UCA0CTL0 = UCMODE_3;						// No parity, LSB first, 8b data, one stop bit, UART mode, async mode, UCMODE = 11b [auto baud rate detect uart]
	UCA0CTL1 = UCSWRST | UCSSEL_2; // | UCDORM;		// SMCLK source, no interrupts, not dormant, no break, no addr chars, hold in reset, don't put BRK in RXBUF0
	UCA0ABCTL = UCABDEN;						// Auto baud-rate detect enable
	UCA0BR0 = 3;//79;								// Pre-scaler in UCA0BR[0|1] should be set upon auto-baud rate detection
	UCA0BR1 = 0;								
	UCA0MCTL = 0x27;
	UCA0MCTL = UCBRS_0 | UCBRF_6 + UCOS16;//UCBRS_0 | UCBRF_13 + UCOS16;		// Over-sampling enabled
	
	
	UCA0CTL1 &= ~UCSWRST; 						// Relase from reset
	
	UCA0IE |= UCRXIE;							// Enable UART RX interrupts for message processing
}
void SendSeveralBytes(unsigned char *data, unsigned char length)
{
	unsigned char i;
	
	for (i = 0; i< length; i++)
	{
		while(!(UCA0IFG & UCTXIFG));
		UCA0TXBUF = data[i];
	}
}
void send_breakSynch_ACK(void)
{
	response_buffer_ACK[0] = cmdMsg_breakSynch;
	response_buffer_ACK[1] = 0;
	response_buffer_ACK[2] = 0;
	response_buffer_ACK[3] = 0;
	response_buffer_ACK[4] = cmdMsg_breakSynch;
//	SendSeveralBytes(&response_buffer_ACK[0],5);
	uart_transmit(&response_buffer_ACK[0], 5);
}
void send_dataStream(unsigned char _cmd)
{	
	int i;
	unsigned int data1 = AppCurrentFiltered;
	unsigned int data2 = AppCurrent;
	unsigned int data3 = pwm_duty;
	unsigned int data4 = AppTemperature;
	unsigned int data5 = AppOverCurrent;
	unsigned char cmdWord = 3;
	unsigned char numDataWords = 5;
//	unsigned int data5 = AppSpeed;
	
	response_buffer_ACK[0] = _cmd;
	response_buffer_ACK[1] = cmdWord;
	response_buffer_ACK[2] = numDataWords;
	response_buffer_ACK[3] = data1>>8;
	response_buffer_ACK[4] = data1 & 0xFF;
	response_buffer_ACK[5] = data2>>8;
	response_buffer_ACK[6] = data2 & 0xFF;
	response_buffer_ACK[7] = data3>>8;
	response_buffer_ACK[8] = data3 & 0xFF;
	response_buffer_ACK[9] = data4>>8;
	response_buffer_ACK[10] = data4 & 0xFF;
	response_buffer_ACK[11] = data5>>8;
	response_buffer_ACK[12] = data5 & 0xFF;
	response_buffer_ACK[13] = 0;
	for (i = 0; i < 13; i++)
	{
		response_buffer_ACK[13] += response_buffer_ACK[i];
	}
//	SendSeveralBytes(&response_buffer_ACK[0],5);
	uart_transmit(&response_buffer_ACK[0], (numDataWords*2)+4);
}
void send_cmd(unsigned char _cmd, unsigned int _data)
{	
	int i;
	
	response_buffer_ACK[0] = _cmd;
	response_buffer_ACK[1] = 3;
	response_buffer_ACK[2] = _data>>8;
	response_buffer_ACK[3] = _data & 0xFF;
	response_buffer_ACK[4] = 0;
	for (i = 0; i < 4; i++)
	{
		response_buffer_ACK[4] += response_buffer_ACK[i];
	}
//	SendSeveralBytes(&response_buffer_ACK[0],5);
	uart_transmit(&response_buffer_ACK[0], 5);
}
/*
 * \fn uart_tick_1ms()
 * \brief Called by user application at 1ms for timeout processing
 */
void uart_tick_1ms()
{
	// First, check for rx message timeout
	
	if (uart_receiving_message)
	{ 
		if (++uart_byte_timer > 100) // 100 ms
			uart_rx_reset();
	}
		
	// Now, call transmit state machine
	if (uart_transmitting_message)
		uart_tx_state_machine();
	
}


/*
 * \fn void uart_transmit()
 * \brief Initiates a transmit of data out the UART with the given data pointer and length.
 */
void uart_transmit(unsigned char *data, unsigned char num_bytes)
{
	if (uart_transmitting_message == 0)
	{
		// Store number of bytes to send, and pointer to data
		
		tx_bytes_to_send = num_bytes;
		tx_byte_count = 0;
		tx_data_ptr = data;
		uart_transmitting_message = 1;
		uart_tx_state = tx_state_delay;
		uart_byte_timer = 0;
	
		// Enable receive and interrupts and let state machine take over
	
//		UCA0IE |= UCTXIE;
	}
} 
 

/*
 * \fn void uart_tx_state_machine()
 * \brief UART transmit state machine that runs when the user wants to transmit data out the UART.
 */
void uart_tx_state_machine()
{
	static unsigned char tx_delay = 0;
	uart_tx_state = tx_state_send_byte;
	switch (uart_tx_state)
	{
		case tx_state_delay:
			
			if (++tx_delay == 2)
			{
				uart_tx_state = tx_state_send_byte;
				tx_delay = 0;
			}
			break;
		
		case tx_state_send_byte:
//			P2OUT &= ~BIT0;
			while ((UCA0STAT&BIT0)==BIT0);
//			P2OUT |= BIT0;
			UCA0TXBUF = *tx_data_ptr++;
			
			if (++tx_byte_count == tx_bytes_to_send)
			{
				UCA0IE &= ~UCTXIE;
				uart_tx_state = tx_state_idle;
				uart_transmitting_message = 0;
			}
			else
				uart_tx_state = tx_state_delay;
					
			break;
	}
}


/*
 * \fn void uart_rx_reset()
 * \brief Reset the RX state machine, after a timeout or other failure
 */
void uart_rx_reset()
{	
	uart_receiving_message = 0;								// Reset indicator for receiving message
	uart_transmitting_message = 0;							// Reset indicator for transmitting message
	rx_byte_count = 0;										// Reset byte count to 0, so gets put in buffer properly
	tx_byte_count = 0;										// Reset byte count to 0
	uart_byte_timer = 0;
	curr_data_ptr = rx_data_ptr;							// Reset data pointer
	UCA0CTL1 |= UCDORM;										// Drop all characters until the BRK/SYNC field is received
	UCA0IE &= ~UCTXIE;
	UCA0IFG &= ~(UCRXIFG | UCTXIFG);						// Clear any pending interrupts (receive or transmit)
}
/*
 * \fn void uart_rx_state_machine()
 * \brief UART receive state machine that runs when characters are received on the UART
 */
void uart_rx_state_machine(unsigned char data)
{
	*curr_data_ptr++ = data;
	
	if (!uart_receiving_message)
	{
		uart_receiving_message = 1;							// Started receiving new message
		
	}
	
	if (++rx_byte_count == UART_MESSAGE_SIZE) 				// last byte
	{
		rx_byte_count = 0;
		uart_receiving_message = 0;							// Done receiving message
		msg_protocol_handler();								// Application callback when message received
		curr_data_ptr = rx_data_ptr;						// Set up receive buffer for next message
		//UCA0CTL1 |= UCDORM;									// Drop all characters until the BRK/SYNC field is received for next message
	}		
}


//
// INTERRUPTS
//

/*
 * \fn interrupt void uart_rx_tx()
 * \brief Handles UART Rx and Tx interrupts and dispatches to the state machines
 */
#pragma vector = USCI_A0_VECTOR
interrupt void uart_rx_tx(void)
{
	if (UCA0IV == USCI_UCRXIFG)
	{
		// If we got a BRK/SYNC character, clear UCDORM so we receive all other characters
		// until end of message
		
		if ((UCA0STAT & UCBRK) != 0)
		{
			UCA0CTL1 &= ~UCDORM;								// Allow generation of UCRXIFG for all received bytes
			UCA0STAT &= ~UCBRK;									// Clear the break condition
	//		while (!(UCA0IFG & UCTXIFG));
	//			UCA0TXBUF = cmdMsg_breakSynch;
			send_breakSynch_ACK();
		} 
		
		uart_rx_state_machine(UCA0RXBUF);					// Non-control character received, pass to state machine
		
		UCA0IFG &= ~UCRXIFG;
	}
	else
	{
//		uart_tx_state_machine();
		
		UCA0IFG &= ~UCTXIFG;
	}
}


